
	import java.awt.*;
	import java.awt.event.*;
	import javax.swing.*;
	import java.util.*;

	public class Huff extends JFrame
	{
		private JLabel ltab1, ltab2,labelsim,labelfrec;
		private JButton jbintab1,jbintab2, codi_frase, salir;
		private JPanel dialogo;
		private JTabbedPane jtabpane;
		public LinkedList lista1;
		private Trans [] Codigos;	
		public Trans [] mensaje;
		public Trans [] masBajos;
		private Trans b,c;
		double longitud=0,entropia=0,acumula=0;
		public LinkedList lista2;
		JDialog jd;
		int m=0;
		JLabel label1;
		JLabel label2;
		JLabel label3;
	
		Cadena frac;
	    Probabilidades frecuencia;	
		ManejaEvento evento = new ManejaEvento();
	
	public Huff()
	{
		super("Algoritmo de Huffman");
			
		lista1 = new LinkedList();
    	lista2 = new LinkedList();
    	
		jd = new JDialog(this,"Algoritmo de Huffman",false);
		
		codi_frase = new JButton("Codificar Frases");
		codi_frase.setBackground(Color.black);
		codi_frase.setForeground(Color.WHITE);
		
		salir = new JButton("Salir Del Programa");
		salir.setBackground(Color.black);
		salir.setForeground(Color.white);
		
		//  boton de frases		
		codi_frase.addActionListener(new ActionListener()
		{	
		 public void actionPerformed(ActionEvent r)
	    	{
			 jd.hide();			
			 Frase();		
			 frac.boton.addActionListener(evento);
		    }
		});
		
			

 salir.addActionListener(new ActionListener()
	{	
		public void actionPerformed(ActionEvent r)
		{
			System.exit(0);
		}
	});	
		
		//añadimos la opciones al panel principal	
			dialogo = new JPanel();
			dialogo.add(codi_frase);
			dialogo.add(salir);
			
			jd.add(dialogo);
			jd.setSize(300,150);
			dialogo.setBackground(Color.BLACK);
			jd.setLocationRelativeTo(null);
		jd.show();		
		this.getContentPane().add(jd);
	}
	
	// son los dos frames	
	public void Frase()  // el de transformar string's
	{
		frac = new Cadena();
		this.getContentPane().add(frac);
		this.setSize(550,150);
		this.setLocationRelativeTo(null);
		this.setVisible(true);
	}
	
	public void Frecuencia()   // el de transformar probabilidades
	{
		JFrame frame = new JFrame();
		frame.setTitle("Codificacion con Probabilidades");
		frecuencia = new Probabilidades();
		frame.getContentPane().add(frecuencia);
		frame.setSize(450,150);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
	}
		
	public void Mensaje(String mensaje)
	{
	 int n_d_simbolos=2;
    	try
    	 {
   		  n_d_simbolos = Integer.parseInt(frac.forma2);
    	   if(n_d_simbolos>1 && n_d_simbolos<10 )
    	    {
    	      CodificancoFrase(mensaje);
		      Proceso(lista1,(lista1.size()),n_d_simbolos);
		      Mostrar(lista2);
            }else
    	     {
    	        JOptionPane.showMessageDialog(null,"Error al insertar la cantidad de simbolos del Codificador");
    	     }    
    	 }catch(NumberFormatException h)
    	  {
    	     JOptionPane.showMessageDialog(null,"Error al insertar la cantidad de simbolos del Codificador");
    	  }
    }
    
    public void CodificancoFrase(String frase)
    {
    	for(int i=0; i<frase.length() ; i++)
    	{
    	 Trans si = new Trans();
    	 si.setSim(frase.substring(i,i+1));
    	 si.setProb(1);
    	 int a = 0;
    	 boolean flag = false;
    	 if(lista1.size()>0)
    	  do{
    	     Trans so = (Trans) lista1.get(a);	
    			if(so.equals(si)){
    				so.setProb(si.getProb());
    				flag = true;
    		}
    	 else if(a==(lista1.size()-1))
    	 {
    		flag = true;
    		lista1.add(si);
    		m++;
    	 }
    	a++;
    	}
    	while((flag == false));
    	 else
    	 {
    	 	lista1.add(si);
    		m++;
    	 }
    	}
    	Trans [] mensaje = new Trans[m];
    	Codigos = new Trans[m];
    	for(int a = 0 ; a<m ; a++)
    	{
    	   mensaje[a] = (Trans) lista1.get(a);
    	   Codigos[a] = new Trans(mensaje[a].getSymb(), mensaje[a].getProb());
    	   lista2.add(Codigos[a]);
    	}
    }
    
    public void CodifProb(int m, int s)
    {
	  	lista2 = new LinkedList();
    	Codigos = new Trans[m];
    	Trans [] mensaje = new Trans[m];
    	for(int i=0;i<m;i++)
    	{
    	  boolean flag = false;
    	  do
    	  {
    		mensaje[i] = new Trans("S"+(i+1), Double.parseDouble(JOptionPane.showInputDialog("Probabilidad del mensaje #" + (i+1))));
    		Codigos[i] = new Trans("S"+(i+1),mensaje[i].getProb());
    		if(mensaje[i].getProb()<=1 && mensaje[i].getProb()>0)
    		{
    	     lista2.add(Codigos[i]);
    	     lista1.add(mensaje[i]);
    	     flag = true;
    	    }
    	    else
    	    JOptionPane.showMessageDialog(null,"Ingrese las probabilidades entre 0 y 1");
    	 }while(flag == false);
    	}
    	Proceso(lista1,m,s);
    	Mostrar(lista2);
    }
    
    public void Proceso(LinkedList sec, int m, int s)
    {
    	Inicio(sec,m);
    	Fin(sec,m,s);
    }
     
    public void MCodigo(Trans sy, String c, int m)
    {
	  try
	  {
		Trans simbolo = new Trans("",0.0);
		for(int i=0;i<sy.getSymb().length(); i++)
		{
			if(sy.getSymb().substring(i,i+1).equals(",")==false && (i+1)<sy.getSymb().length())
				simbolo.setSim(sy.getSymb().substring(i,i+1));
			else if(sy.getSymb().substring(i,i+1).equals(",")==true)
			{
			 for(int a=0; a<lista2.size(); a++)
				if(simbolo.equals(lista2.get(a)))
				{
					simbolo = (Trans)lista2.get(a);
					simbolo.setCod(c);
					lista2.remove(a);
					lista2.add(a,simbolo);
				}
			  simbolo = new Trans("",0.0);
	 		}
		else if(i==(sy.getSymb().length()-1))
		{
			simbolo.setSim(sy.getSymb().substring((sy.getSymb().length()-1),sy.getSymb().length()));
		for(int a=0; a<lista2.size(); a++)
			if(simbolo.equals(lista2.get(a)))
				{
					simbolo = (Trans)lista2.get(a);
					simbolo.setCod(c);
					lista2.remove(a);
					lista2.add(a,simbolo);
				}
		}
	}
	}catch(NullPointerException n){
	}
   }
    
    public void Fin(LinkedList sec, int m, int s)
    {
   		mensaje = new Trans[m];
   		masBajos = new Trans[s+1];
    	for(int i=0; i<sec.size(); i++)
    	 {
        	mensaje[i] = (Trans) sec.get(i);
              if((m-i)<=s)
              	{
    				masBajos[m-i]= mensaje[i];
   				 }
    	}	
    	for(int i=1; i<=s; i++)
    	{
    		if(i==s)
    		{
    			MCodigo(masBajos[i], "0", m);
    		}
    		else if((i-1)==0)
    		{
   				 MCodigo(masBajos[i], (""+(s-1)), m);
    		}
    		else
    		{
    			MCodigo(masBajos[i], ""+((i-1)), m);
    		}
    	if(i>1){
    	try{
    		masBajos[1].setSim(","+masBajos[i].getSymb());
    		masBajos[1].setProb(masBajos[i].getProb());
   			 sec.remove(masBajos[i]);
    	}catch(NullPointerException n){}
    	}
   	 }
     if(sec.size()>1)
        Proceso(sec,((m-s)+1),s);
    }
    
    public void Inicio(LinkedList sec, int m)
    {
   	 for(int i=m; i>1; i--)
    	for(int a=0; a<m ; a++)
    	{
   			if(a<(m-1))
   			{
    		 try
    		 {
   				 b = (Trans) sec.get(a);
   			 }catch(Exception e){
    								LinkedList lista = (LinkedList)sec.get(a);
   								    b = new Trans();
   								    b.setProb((Double)lista.getLast());
    							}
   		 	try{
    				c = (Trans) sec.get(a+1);
    			}catch(Exception e){
    								LinkedList lista = (LinkedList)sec.get(a+1);
    								c = new Trans();
    								c.setProb((Double)lista.getLast());
    								}
    		if(b.getProb()<c.getProb())
    		{
    			int posb = lista1.indexOf(b);
    			sec.remove(posb);
    			sec.remove(posb);
    			sec.add(posb, b);
    			sec.add(posb, c);
    		}
    	  }		
     }
  }
    
    public void Mostrar(LinkedList l)
    {
	  JDialog impre = new JDialog();
	  JPanel texto = new JPanel();
	  texto.setLayout(new GridLayout(l.size()+1,4));
	  texto.add(new JLabel("Simbolo"));
	  texto.add(new JLabel("Probabilidad"));
	  texto.add(new JLabel("Codigo"));
	  
	  for(int f=0;f<l.size();f++)
		   {
		   	 Trans s=(Trans) l.get(f);
		     double v = Double.parseDouble(""+s.getProb());
		   	 acumula=acumula+v;		   			   	
		   }
	  
	for(int i =0 ; i< l.size() ; i++)
	{
		Trans s = (Trans) l.get(i);
		texto.add(new JLabel());
		texto.add(new JLabel("   "+s.getSymb()));
		texto.add(new JLabel(" "+s.getProb()));	
		texto.setBackground(Color.green);
		texto.add(new JLabel(" "+s.getCod()));
		
		double g= Double.parseDouble(""+s.getProb());
	       double k=g/acumula;      
		  
		   longitud=longitud+(k*s.getCod().length());
		   entropia=entropia+(k*(-1*Math.log10(k)));
	}
	    jd.setVisible(true);
	    impre.add(texto);
    	impre.setTitle("Codificaciòn");
		impre.setSize(400,500);
		impre.setVisible(true);	
	JOptionPane.showMessageDialog(null,"La longitud es  "+longitud+"\n La Entropia es  "+entropia);	
   }

  public class ManejaEvento implements ActionListener
	{
		public void actionPerformed(ActionEvent a)
		{
			String cadena=a.getActionCommand();
			if(cadena.equals("Realizar Proceso"))
			{
				Cadena ss = new Cadena();
				if(frac.cadena.getText()!= "")	
				{
					String mensaje=frac.cadena.getText().toString();
					Mensaje(mensaje);
				}else
				{
					JOptionPane.showMessageDialog(null,"Campos Vacios");
				}
			}
		if(cadena.equals("Procesar Datos"))
		{
			try
			{
				int m = Integer.parseInt(frecuencia.num_prob.getText());
				int symbols = Integer.parseInt(frecuencia.codigo.getText());
				if (symbols > 1 && symbols < 10)
				{
   					CodifProb(m, symbols);
   				}
			}catch(NumberFormatException h)
    		{
    			JOptionPane.showMessageDialog(null,"Error al insertar la cantidad de mensajes o simbolos del Codificador");
    		}
    	}
	 }
   }
	
 public static void main(String[] args)
	{
		Huff f=new Huff();
	}
}